package server

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
	"stock_ths/config"
	"stock_ths/hq"
	lg "stock_ths/log"
)

type DaysData struct {
	Dates []string `json:"dates"`
	Data  [][]int  `json:"data"`
	Curve [][]int  `json:"curve"`
}

func getDaysData(w http.ResponseWriter, r *http.Request) {
	code := r.URL.Query().Get("code")
	lg.ILogger.Println("code:", code)
	dates, ds, err := hq.GetDays(code, "")
	if err != nil {
		writeError(w, r, err)
		return
	}

	var result DaysData
	// result := map[string]([][]int){}
	result.Dates = dates
	result.Data = ds
	result.Curve = make([][]int, 0)

	js, err := json.Marshal(result)
	if err != nil {
		writeError(w, r, err)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.Write(js)
}

func calculateMA(dayCount int, data [][]int) [][]int {
	result := [][]int{}
	for i := 0; i < len(data); i++ {
		if i < dayCount {
			result = append(result, []int{0, 0, 0, 0, 0})
			continue
		}
		sum := []int{0, 0, 0, 0, 0}
		for j := 0; j < dayCount; j++ {
			sum[0] += data[i-j][0]
			sum[1] += data[i-j][1]
			sum[2] += data[i-j][2]
			sum[3] += data[i-j][3]
			sum[4] += data[i-j][4]
		}
		// result.push(sum / dayCount)
		result = append(result, []int{sum[0] / dayCount, sum[1] / dayCount, sum[2] / dayCount, sum[3] / dayCount, sum[4] / dayCount})
	}

	return result
}

// 计算 最低点/开盘价/最高点/收盘价的均值/成交量
func averageCalculate(vs [][]int) []int {
	r := make([]int, hq.DataArraySize)
	if len(vs) <= 0 {
		return r
	}

	for _, v := range vs {
		if len(v) != hq.DataArraySize {
			continue
		}

		for i := 0; i < hq.DataArraySize; i++ {
			r[i] = r[i] + v[i]
		}
	}

	for i := 0; i < hq.DataArraySize; i++ {
		r[i] = r[i] / len(vs)
	}

	return r
}

// 生成训练数据集
func generateTrainData(dates []string, values [][]int) {
	trainDatas := ""
	trainLabels := ""
	for k, v := range values {
		if k == len(values)-1 {
			break
		}

		if k%5 == 0 {
			tv := float32(v[3]-v[1]) / float32(v[1])
			line := ""
			if tv < -0.1 {
				line = fmt.Sprintf("%s,%d\n", dates[k], -5)
			} else if tv < -0.08 {
				line = fmt.Sprintf("%s,%d\n", dates[k], -4)
			} else if tv < -0.06 {
				line = fmt.Sprintf("%s,%d\n", dates[k], -3)
			} else if tv < -0.04 {
				line = fmt.Sprintf("%s,%d\n", dates[k], -2)
			} else if tv < -0.02 {
				line = fmt.Sprintf("%s,%d\n", dates[k], -1)
			} else if tv < 0.0 {
				line = fmt.Sprintf("%s,%d\n", dates[k], 0)
			} else if tv <= 0.02 {
				line = fmt.Sprintf("%s,%d\n", dates[k], 1)
			} else if tv <= 0.04 {
				line = fmt.Sprintf("%s,%d\n", dates[k], 2)
			} else if tv <= 0.06 {
				line = fmt.Sprintf("%s,%d\n", dates[k], 3)
			} else if tv <= 0.08 {
				line = fmt.Sprintf("%s,%d\n", dates[k], 4)
			} else if tv <= 0.1 {
				line = fmt.Sprintf("%s,%d\n", dates[k], 5)
			} else {
				line = fmt.Sprintf("%s,%d\n", dates[k], 6)
			}
			trainLabels = trainLabels + line
			dline := fmt.Sprintf("%s,%d,%d,%d,%d,%d\n", dates[k], v[0], v[1], v[2], v[3], v[4])
			trainDatas = trainDatas + dline
		} else {
			line := fmt.Sprintf("%s,%d,%d,%d,%d,%d\n", dates[k], v[0], v[1], v[2], v[3], v[4])
			trainDatas = trainDatas + line
		}
	}

	f1, err := os.OpenFile("train_data.csv", os.O_TRUNC|os.O_RDWR, 0666)
	if err != nil {
		lg.ELogger.Println("open train_data.csv:", err)
		return
	}
	f2, err := os.OpenFile("train_label.csv", os.O_TRUNC|os.O_RDWR, 0666)
	if err != nil {
		lg.ELogger.Println("open train_label.csv:", err)
		return
	}

	n, err := io.WriteString(f1, trainDatas)
	if err != nil {
		lg.ELogger.Println("WriteString:", err)
		return
	}
	lg.ILogger.Println("write trainDatas len=", n)

	n, err = io.WriteString(f2, trainLabels)
	if err != nil {
		lg.ELogger.Println("WriteString:", err)
		return
	}
	lg.ILogger.Println("write trainDatas len=", n)

}

func getBreakCurve(w http.ResponseWriter, r *http.Request) {
	code := r.URL.Query().Get("code")
	// days := r.URL.Query().Get("days")
	lg.ILogger.Println("code:", code)
	dates, values, err := hq.GetDays(code, "")
	if err != nil {
		writeError(w, r, err)
		return
	}

	// idays, err := strconv.Atoi(days)
	// if err != nil {
	// 	writeError(w, r, err)
	// 	return
	// }

	head := "日期,最低价,开盘价,最高价,收盘价,最低均值,开盘价均值,最高价均值,收盘价均值,成交量\n"

	fileName := "days.csv"
	var f *os.File
	// var err error
	if config.CheckFileIsExist("days.csv") {
		f, err = os.OpenFile(fileName, os.O_TRUNC|os.O_RDWR, 0666)
	} else {
		f, err = os.Create(fileName)
	}
	if err != nil {
		lg.ELogger.Println("open or create file:", err)
		return
	}

	var lines string = head

	// sumDays := make([][]int, 0)
	// 计算5日均值
	average := calculateMA(5, values)

	if len(values) != len(average) {
		lg.ELogger.Println("aravage:", len(average), ",values:", len(values))
		return
	}
	for k, v := range values {
		line := fmt.Sprintf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", dates[k], v[0], v[1], v[2], v[3], average[k][0], average[k][1], average[k][2], average[k][3], v[4])
		lines = lines + line
	}
	// for k, v := range values {
	// 	if len(v) != hq.DataArraySize {
	// 		continue
	// 	}

	// 	l := v[0] // k这一天对应的最低价
	// 	if l <= 0 {
	// 		continue
	// 	}
	// 	s := v[1] // k这一天对应的开盘价与最低价差
	// 	h := v[2] // k这一天对应的最高价与最低价差
	// 	e := v[3] // k这一天对应的收盘价与最低价差
	// 	q := v[4] // k这一天对应的成交量

	// 	// sl := s + l
	// 	// hl := h + l
	// 	// el := e + l
	// 	t := []int{l, s, h, e, q}
	// 	sumDays = append(sumDays, t)
	// 	if len(sumDays) > idays {
	// 		sumDays = sumDays[len(sumDays)-idays:]
	// 	}

	// 	// av := averageCalculate(sumDays)
	// 	// average[k] = av
	// 	line := fmt.Sprintf("%s,%d,%d,%d,%d,%d,%d,%d,%d,%d\n", dates[k], l, s, h, e, q, av[0], av[1], av[2], av[3])
	// 	lines = lines + line
	// }

	n, err := io.WriteString(f, lines)
	if err != nil {
		lg.ELogger.Println("WriteString:", err)
		return
	}
	lg.ILogger.Println("WriteString len=", n)

	var result DaysData
	// result := map[string]([][]int){}
	result.Dates = dates
	result.Data = values
	result.Curve = average

	js, err := json.Marshal(result)
	if err != nil {
		lg.ELogger.Println("Marshal:", err)
		writeError(w, r, err)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.Write(js)
}

func getTimesData(w http.ResponseWriter, r *http.Request) {
	code := r.URL.Query().Get("code")
	ds, err := hq.GetTime(code, "")
	if err != nil {
		lg.ELogger.Println("GetTime:", err)
		writeError(w, r, err)
		return
	}

	js, err := json.Marshal(ds)
	if err != nil {
		lg.ELogger.Println("Marshal:", err)
		writeError(w, r, err)
		return
	}

	w.WriteHeader(http.StatusOK)
	w.Write(js)
}
